﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace ListItemEditor.UI
{
    public class DataGridViewTextBoxIconCell : DataGridViewTextBoxCell
    {
        #region properties

        private DataGridViewTextBoxIconColumn ParentColumn
        {
            get { return this.OwningColumn as DataGridViewTextBoxIconColumn; }
        }

        #endregion

        #region overrides

        protected override void OnMouseClick(DataGridViewCellMouseEventArgs e)
        {
            base.OnMouseClick(e);

            if (e.Button != MouseButtons.Left) return;
            // test for shared row
            if (this.DataGridView == null || this.OwningRow.Index < 0) return;

            // this throws on a shared row
            if (!this.IsInEditMode) return;
            if (this.ParentColumn.IconProvider == null) return;

            Rectangle bitmapRect = this.GetBitmapRect(new Rectangle(0, 0, this.Size.Width, this.Size.Height), e.RowIndex);
            if (bitmapRect.Contains (e.Location)) this.ParentColumn.IconProvider.OnIconMouseClick (this, e.RowIndex);
        }

        protected override void OnMouseMove(DataGridViewCellMouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (this.DataGridView == null) return;
            if (this.ParentColumn.IconProvider == null) return;
            // shared row
            if (this.OwningRow.Index < 0) return;

            Rectangle bitmapRect = this.GetBitmapRect(new Rectangle(0, 0, this.Size.Width, this.Size.Height), e.RowIndex);
            if (bitmapRect.Contains(e.Location)) Cursor.Current = Cursors.Hand;
            else Cursor.Current = Cursors.Arrow;
        }

        protected override Rectangle GetContentBounds(Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex)
        {
            // TODO - override this one properly - for the tooltip
            return base.GetContentBounds(graphics, cellStyle, rowIndex);
        }

        public override void PositionEditingControl(bool setLocation, bool setSize, Rectangle cellBounds, Rectangle cellClip, DataGridViewCellStyle cellStyle, bool singleVerticalBorderAdded, bool singleHorizontalBorderAdded, bool isFirstDisplayedColumn, bool isFirstDisplayedRow)
        {
            Rectangle newCellBounds = this.GetCorrectedTextBoundRect(cellBounds, -1);
            base.PositionEditingControl(setLocation, setSize, newCellBounds, cellClip, cellStyle, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedColumn, isFirstDisplayedRow);
        }

        protected override void Paint(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
        {
            Rectangle bitmapRect = this.GetBitmapRect(cellBounds, rowIndex);
            if (bitmapRect.Width == 0 || bitmapRect.Height == 0)
            {
                base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
                return;
            }

            // store the text value and paint the cell without it
            object originalFormattedValue = formattedValue;
            base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, "", errorText, cellStyle, advancedBorderStyle, paintParts);

            Rectangle textCellBounds = this.GetCorrectedTextBoundRect(cellBounds, rowIndex);
            // paint just the text value in the corrected text bounds
            base.Paint(graphics, clipBounds, textCellBounds, rowIndex, cellState, value, originalFormattedValue, errorText, cellStyle, advancedBorderStyle, DataGridViewPaintParts.ContentForeground);

            Bitmap bitmap = GetBitmap(rowIndex);
            if (bitmap != null && bitmapRect.Width > 0 && bitmapRect.Height > 0) graphics.DrawImageUnscaledAndClipped(bitmap, bitmapRect);
        }
        
        #endregion

        #region private

        private Bitmap GetBitmap(int rowIndex)
        {
            if (this.ParentColumn.IconProvider == null) return null;
            int idx = this.ParentColumn.IconProvider.GetIconIndex(this, rowIndex);
            if (this.ParentColumn.Bitmaps == null || idx < 0 || idx >= this.ParentColumn.Bitmaps.Count) return null;
            return this.ParentColumn.Bitmaps[idx];
        }

        private Rectangle GetCorrectedTextBoundRect(Rectangle cellBounds, int rowIndex)
        {
            Rectangle dropDownButtonRect = this.GetBitmapRect(cellBounds, rowIndex);
            if (dropDownButtonRect.Width <= 0 || dropDownButtonRect.Height <= 0) return cellBounds;
            return new Rectangle(cellBounds.Location, new Size(cellBounds.Width - dropDownButtonRect.Width - 3, cellBounds.Height));
        }

        private Rectangle GetBitmapRect(Rectangle cellBounds, int rowIndex)
        {
            Bitmap bitmap = this.GetBitmap(rowIndex);
            if (bitmap == null) return Rectangle.Empty;

            int height = Math.Max(Math.Min(cellBounds.Height - 4, bitmap.Height), 0);
            int width = Math.Max(Math.Min(bitmap.Width, cellBounds.Width - 4), 0);
            Rectangle rect = new Rectangle(cellBounds.Right - width - 3, cellBounds.Top + 2, width, height);
            return rect;
        }

        #endregion
    }
}